package app

import (
	"fmt"
	"os"
	"os/signal"
	"strings"
	"syscall"

	"github.com/fatih/color"
	"github.com/spf13/cobra"
	"gs-demo-ftp-sync/internal/config"
	"gs-demo-ftp-sync/internal/ftp"
	"gs-demo-ftp-sync/internal/watcher"
)

// App 应用程序结构
type App struct {
	config    *config.Config
	ftpClient *ftp.Client
	fileWatcher *watcher.Watcher
}

// NewApp 创建新的应用程序
func NewApp() (*App, error) {
	// 加载配置
	cfg, err := config.Load()
	if err != nil {
		return nil, err
	}

	// 创建FTP客户端
	ftpClient := ftp.NewClient(cfg)

	// 创建文件监控器
	fileWatcher := watcher.NewWatcher(cfg, ftpClient)

	return &App{
		config:      cfg,
		ftpClient:   ftpClient,
		fileWatcher: fileWatcher,
	}, nil
}

// Run 运行应用程序
func Run() error {
	app, err := NewApp()
	if err != nil {
		return err
	}

	// 创建根命令
	var rootCmd = &cobra.Command{
		Use:   "gs-demo-ftp-sync",
		Short: "GS Demo FTP实时同步工具",
		Long:  "自动同步 gs_demo_thinkphp 插件文件到远程FTP服务器",
	}

	// 添加子命令
	rootCmd.AddCommand(app.newSyncCommand())
	rootCmd.AddCommand(app.newWatchCommand())
	rootCmd.AddCommand(app.newFullSyncCommand())
	rootCmd.AddCommand(app.newTestCommand())

	// 执行命令
	return rootCmd.Execute()
}

// newSyncCommand 创建同步命令
func (a *App) newSyncCommand() *cobra.Command {
	return &cobra.Command{
		Use:   "sync",
		Short: "同步变更的文件",
		Long:  "基于git状态同步已变更的文件到FTP服务器",
		RunE: func(cmd *cobra.Command, args []string) error {
			return a.runSync()
		},
	}
}

// newWatchCommand 创建监控命令
func (a *App) newWatchCommand() *cobra.Command {
	return &cobra.Command{
		Use:   "watch",
		Short: "启动文件监控模式",
		Long:  "监控文件变化并实时同步到FTP服务器",
		RunE: func(cmd *cobra.Command, args []string) error {
			return a.runWatch()
		},
	}
}

// newFullSyncCommand 创建完整同步命令
func (a *App) newFullSyncCommand() *cobra.Command {
	return &cobra.Command{
		Use:   "full-sync",
		Short: "完整同步所有文件",
		Long:  "将所有文件同步到FTP服务器，适合首次部署",
		RunE: func(cmd *cobra.Command, args []string) error {
			return a.runFullSync()
		},
	}
}

// newTestCommand 创建测试命令
func (a *App) newTestCommand() *cobra.Command {
	return &cobra.Command{
		Use:   "test",
		Short: "测试FTP连接",
		Long:  "测试FTP服务器连接是否正常",
		RunE: func(cmd *cobra.Command, args []string) error {
			return a.runTest()
		},
	}
}

// runSync 执行同步
func (a *App) runSync() error {
	color.Blue("🚀 GS Demo FTP同步工具")
	color.Gray("=" + strings.Repeat("=", 49))
	
	a.config.Display()

	color.Blue("执行一次性同步...")

	// 连接FTP
	if err := a.ftpClient.Connect(); err != nil {
		return fmt.Errorf("FTP连接失败: %v", err)
	}
	defer a.ftpClient.Disconnect()

	// 这里可以实现基于git的变更检测
	// 暂时执行完整同步
	if err := a.syncAllDirectories(); err != nil {
		return fmt.Errorf("同步失败: %v", err)
	}

	color.Green("✅ 同步完成")
	return nil
}

// runWatch 执行监控模式
func (a *App) runWatch() error {
	color.Blue("🚀 GS Demo FTP同步工具")
	color.Gray("=" + strings.Repeat("=", 49))
	
	a.config.Display()

	color.Blue("启动文件监控模式...")

	// 连接FTP
	if err := a.ftpClient.Connect(); err != nil {
		return fmt.Errorf("FTP连接失败: %v", err)
	}

	// 启动文件监控
	if err := a.fileWatcher.Start(); err != nil {
		return fmt.Errorf("启动文件监控失败: %v", err)
	}

	// 设置信号处理
	sigChan := make(chan os.Signal, 1)
	signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)

	color.Green("✅ 监控已启动，只会在文件变化时上传，按 Ctrl+C 停止")
	color.Yellow("📝 提示：如需初次完整同步，请运行 gs-demo-ftp-sync full-sync")

	// 等待中断信号
	<-sigChan
	color.Yellow("\n收到中断信号，正在停止...")

	// 清理资源
	a.cleanup()
	return nil
}

// runFullSync 执行完整同步
func (a *App) runFullSync() error {
	color.Blue("🚀 GS Demo FTP同步工具")
	color.Gray("=" + strings.Repeat("=", 49))
	
	a.config.Display()

	color.Blue("执行完整同步...")

	// 连接FTP
	if err := a.ftpClient.Connect(); err != nil {
		return fmt.Errorf("FTP连接失败: %v", err)
	}
	defer a.ftpClient.Disconnect()

	// 同步所有目录
	if err := a.syncAllDirectories(); err != nil {
		return fmt.Errorf("完整同步失败: %v", err)
	}

	color.Green("✅ 完整同步完成")
	return nil
}

// runTest 执行连接测试
func (a *App) runTest() error {
	color.Blue("🚀 GS Demo FTP同步工具")
	color.Gray("=" + strings.Repeat("=", 49))
	
	a.config.Display()

	// 测试连接
	if err := a.ftpClient.TestConnection(); err != nil {
		return fmt.Errorf("FTP连接测试失败: %v", err)
	}

	color.Green("✅ FTP连接测试成功")
	return nil
}

// syncAllDirectories 同步所有目录
func (a *App) syncAllDirectories() error {
	// 同步插件目录
	if err := a.ftpClient.SyncDirectory(a.config.LocalAddonPath, a.config.RemoteAddonPath); err != nil {
		return fmt.Errorf("同步插件目录失败: %v", err)
	}

	// 同步资源目录
	if err := a.ftpClient.SyncDirectory(a.config.LocalAssetsPath, a.config.RemoteAssetsPath); err != nil {
		return fmt.Errorf("同步资源目录失败: %v", err)
	}

	return nil
}

// cleanup 清理资源
func (a *App) cleanup() {
	if a.fileWatcher != nil {
		a.fileWatcher.Stop()
	}
	if a.ftpClient != nil {
		a.ftpClient.Disconnect()
	}
}
